package bomberman.modelo.personajes;

import org.jdom2.Element;

import bomberman.modelo.IContenible;
import bomberman.modelo.IDaniable;
import bomberman.modelo.armas.Arma;
import bomberman.modelo.armas.OndaExpansiva;
import bomberman.modelo.items.Item;
import bomberman.modelo.mapa.Casillero;
import bomberman.modelo.mapa.Direccion;
import bomberman.modelo.observadores.Observadores;
import fiuba.algo3.titiritero.modelo.ObjetoPosicionable;
import fiuba.algo3.titiritero.modelo.ObjetoVivo;

public abstract class Personaje implements IContenible, IDaniable, ObjetoPosicionable, ObjetoVivo {
	private Arma      arma;
	private Direccion direccion;
	private int       resistencia;
	private int       temporizador;
	private Casillero ubicacion;
	private int       velocidad;
  
	public Personaje(Arma unArma, int unaResistencia, int unTemporizador, Casillero unCasillero, int unaVelocidad) {
	    arma = unArma;
	    direccion = Direccion.SUR;
	    resistencia = unaResistencia;
	    temporizador = unTemporizador;
	    ubicacion = unCasillero;
	    velocidad = unaVelocidad;
	    ubicacion.setContenidoBajo(this);
	    Observadores.notificar(this);
	}

	protected void setArma(Arma nuevaArma) {
		arma = nuevaArma;
	}
  
	protected void setDireccion(Direccion nuevaDireccion) {
		direccion = nuevaDireccion;
	}
  
	protected void setResistencia(int nuevaResistencia) {
		if (nuevaResistencia >= 0) {
			resistencia = nuevaResistencia;
		}
	}
  
	protected void setTemporizador(int nuevoTemporizador) {
		if (nuevoTemporizador >= 0) {
			temporizador = nuevoTemporizador;
		}
	}
  
	protected void setUbicacion(Casillero nuevaUbicacion) {
		ubicacion = nuevaUbicacion;
	}
  
	protected void setVelocidad(int nuevaVelocidad) {
		if (nuevaVelocidad >= 0) {
			velocidad = nuevaVelocidad;
		}
	}
  
	public Arma getArma() {
		return arma;
	}
  
	protected Direccion getDireccion() {
		return direccion;
	}
  
	protected int getResistencia() {
		return resistencia;
	}
  
	public int getTemporizador() {
		return temporizador;
	}
  
	protected Casillero getUbicacion() {
		return ubicacion;
	}
  
	public int getVelocidad() {
		return velocidad;
	}
  
	public boolean puedeCaminarSobre(Item unItem) {
		return false;
	}
  
	/**
	 * Metodo privado para mover. Usar la interfaz publica
	 * 
	 * @param casilleroFinal
	 */
	protected void mover(Casillero casilleroFinal) {
		if (casilleroFinal.esCaminablePor(this)) {
			ubicacion.salgoCaminando(this);
			casilleroFinal.entroCaminando(this);
			ubicacion = casilleroFinal;
		}
	}
  
	public void moverSur() {
		Casillero casilleroDestino = ubicacion.getVecino(Direccion.SUR);
		if (casilleroDestino != null) {
			mover(casilleroDestino);
		}
		
		if (direccion != Direccion.SUR) {
			direccion = Direccion.SUR;
			Observadores.notificar(this);
		}
	}
  
	public void moverNorte() {
		Casillero casilleroDestino = ubicacion.getVecino(Direccion.NORTE);
		if (casilleroDestino != null) {
			mover(casilleroDestino);
		}
		
		if (direccion != Direccion.NORTE) {
			direccion = Direccion.NORTE;
			Observadores.notificar(this);      
		}
	}
  
	public void moverEste() {
		Casillero casilleroDestino = ubicacion.getVecino(Direccion.ESTE);
		if (casilleroDestino != null) {
			mover(casilleroDestino);
		}
		
		if (direccion != Direccion.ESTE) {
			direccion = Direccion.ESTE;
			Observadores.notificar(this);
		}
	}
  
	public void moverOeste() {
		Casillero casilleroDestino = ubicacion.getVecino(Direccion.OESTE);
		if (casilleroDestino != null) {
			mover(casilleroDestino);
		}
		
		if (direccion != Direccion.OESTE) {
			direccion = Direccion.OESTE;
			Observadores.notificar(this);
		}
	}
  
	public void plantarBomba(Direccion direccionDisparo) {
		Casillero casilleroADisparar = null;
		switch (direccionDisparo) {
			case NORTE:
				casilleroADisparar = ubicacion.getVecino(Direccion.NORTE);
				break;
			case SUR:
				casilleroADisparar = ubicacion.getVecino(Direccion.SUR);
				break;
			case OESTE:
				casilleroADisparar = ubicacion.getVecino(Direccion.OESTE);
				break;
			case ESTE:
				casilleroADisparar = ubicacion.getVecino(Direccion.ESTE);
				break;
		}
		
		if (casilleroADisparar != null && casilleroADisparar.getContenidoBajo() == null) {
			arma.disparar(casilleroADisparar, direccionDisparo, temporizador);
		}
	}
  
	public void plantarBomba() {
		plantarBomba(this.getDireccion());
	}
  
	protected void morir() {
		ubicacion.setContenidoBajo(null);
		Item.generarContenidoRandom(ubicacion);
	}
  
	@Override
	public boolean esBalisticamentePermeable() {
		return false;
	}
  
	@Override
	public boolean esCaminablePor(Personaje unPersonaje) {
		return false;
	}
  
	@Override
	public boolean esSobrevolable() {
		return true;
	}
  
	@Override
	public void daniarCon(OndaExpansiva ondaExpansiva) {
		resistencia -= ondaExpansiva.getDestruccion();
		if (resistencia <= 0) {
			resistencia = 0;
			morir();
			Observadores.notificar(this);
		}
	}
  
	@Override
	public int getX() {
		return ubicacion.getPosicion().getHorizontal();
	}
  
	@Override
	public int getY() {
		return ubicacion.getPosicion().getVertical();
	}

	public Element serializar(Element ePersonaje) {
	    ePersonaje.setContent(getUbicacion().serializarUbicacion());
	    ePersonaje.setAttribute("Velocidad", String.valueOf(velocidad));
	    ePersonaje.setAttribute("Resistencia", String.valueOf(resistencia));
	    ePersonaje.setAttribute("Temporizador", String.valueOf(temporizador));
	    ePersonaje.setAttribute("Direccion", String.valueOf(direccion));
	    return ePersonaje;
	}
}
